/* 
 * Copyright 2013 Sébastien Mouquet.
 * 
 * This file is part of ECovoiturage.
 * 
 * ECovoiturage is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * ECovoiturage is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with ECovoiturage. If not, see http://www.gnu.org/licenses/.
 */
package com.smouquet.ecovoiturage.ui.page.root.trajetmidi;

import com.smouquet.ecovoiturage.ApplicationContext;
import com.smouquet.ecovoiturage.core.bean.TrajetMidiFormBean;
import com.smouquet.ecovoiturage.core.bean.TrajetMidiInteresseItem;
import com.smouquet.ecovoiturage.core.domain.Lieu;
import com.smouquet.ecovoiturage.core.domain.Trajet;
import com.smouquet.ecovoiturage.core.domain.TrajetCommentaire;
import com.smouquet.ecovoiturage.core.domain.TrajetUnitisateurId;
import com.smouquet.ecovoiturage.core.domain.TrajetUtilisateur;
import com.smouquet.ecovoiturage.core.domain.Utilisateur;
import com.smouquet.ecovoiturage.core.exception.MailException;
import com.smouquet.ecovoiturage.core.service.LieuService;
import com.smouquet.ecovoiturage.core.service.MailService;
import com.smouquet.ecovoiturage.core.service.TrajetService;
import com.smouquet.ecovoiturage.ui.NotificationUtil;
import com.smouquet.ecovoiturage.ui.page.root.RootUI;
import com.smouquet.ecovoiturage.ui.page.root.trajetmidi.TrajetMidiForm.CommitEvent;
import com.vaadin.navigator.View;
import com.vaadin.navigator.ViewChangeListener.ViewChangeEvent;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.TabSheet;
import com.vaadin.ui.TextArea;
import com.vaadin.ui.TextField;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.Window;
import com.vaadin.ui.themes.Runo;
import java.sql.Time;
import java.text.DateFormat;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

/**
 *
 * @author sebastien.mouquet
 */
public abstract class TrajetMidiAbstractView extends VerticalLayout
                                             implements View, Button.ClickListener,
                                                        TrajetMidiForm.CommitListener
{
    private DateFormat dfTime;
    
    protected Utilisateur currentUtilisateur;
    
    protected TrajetMidiForm form;
    protected Button btnSauvegarder;
    protected Button btnInscription;
    protected Button btnDeinscription;
    protected Button btnCommentaire;
    protected TabSheet tabSheet;
    protected TrajetMidiInteressesTable tblInteresses;
    protected TrajetMidiCommentairesList lstCommentaires;
    
    private Window winInscription;
    private TextField tfNbPlaces;
    private Button btnValiderInscription;
    
    private Window winCommentaire;
    private TextArea taCommentaire;
    private Button btnValiderCommentaire;
    
    
    public TrajetMidiAbstractView()
    {
        this.dfTime = DateFormat.getTimeInstance(DateFormat.SHORT);
    }
    
    
    protected abstract void doAfterSauvegarder(Trajet trajet);
    

    @Override
    public void enter(ViewChangeEvent event)
    {
        currentUtilisateur = getSession().getAttribute(Utilisateur.class);
        
        
        LieuService service = ApplicationContext.getInstance(LieuService.class);
        List<Lieu> lieux = service.getAllOrderByNom();
        
        form = new TrajetMidiForm(lieux);
        form.addCommitListener(this);
        
        HorizontalLayout layoutButtons = new HorizontalLayout();
        layoutButtons.setSpacing(true);
        
        btnSauvegarder = new Button("Sauvegarder");
        btnSauvegarder.addStyleName(Runo.BUTTON_SMALL);
        btnSauvegarder.addStyleName(Runo.BUTTON_DEFAULT);
        btnSauvegarder.addClickListener(this);
        
        btnInscription = new Button("M'inscrire / Modifier mon inscription");
        btnInscription.addStyleName(Runo.BUTTON_SMALL);
        btnInscription.addStyleName(Runo.BUTTON_DEFAULT);
        btnInscription.addClickListener(this);
        
        btnDeinscription = new Button("Me désincrire");
        btnDeinscription.addStyleName(Runo.BUTTON_SMALL);
        btnDeinscription.addStyleName(Runo.BUTTON_DEFAULT);
        btnDeinscription.addClickListener(this);
        
        btnCommentaire = new Button("Ajouter un commentaire");
        btnCommentaire.addStyleName(Runo.BUTTON_SMALL);
        btnCommentaire.addStyleName(Runo.BUTTON_DEFAULT);
        btnCommentaire.addClickListener(this);
        
        layoutButtons.addComponent(btnSauvegarder);
        layoutButtons.addComponent(btnInscription);
        layoutButtons.addComponent(btnDeinscription);
        layoutButtons.addComponent(btnCommentaire);
        
        tabSheet = new TabSheet();
        tabSheet.addStyleName(Runo.TABSHEET_SMALL);
        
        tblInteresses = new TrajetMidiInteressesTable();
        tblInteresses.setSizeUndefined();
        tblInteresses.setWidth(100, Unit.PERCENTAGE);
        tblInteresses.addStyleName(Runo.TABLE_BORDERLESS);
        
        lstCommentaires = new TrajetMidiCommentairesList();
        lstCommentaires.setMargin(true);
        
        tabSheet.addTab(tblInteresses, "Intéressés");
        tabSheet.addTab(lstCommentaires, "Commentaires");
        
        addComponent(form);
        addComponent(layoutButtons);
        addComponent(tabSheet);
        
        setComponentAlignment(layoutButtons, Alignment.MIDDLE_CENTER);
        
        setMargin(true);
        setSpacing(true);
    }

    
    @Override
    public void buttonClick(ClickEvent event)
    {
        if(event.getButton().equals(btnSauvegarder))
        {
            form.doCommit();
        }
        else if(event.getButton().equals(btnInscription))
        {
            doShowInscriptionWindow();
        }
        else if(event.getButton().equals(btnValiderInscription))
        {
            doInscription();
        }
        else if(event.getButton().equals(btnDeinscription))
        {
            doDeinscription();
        }
        else if(event.getButton().equals(btnCommentaire))
        {
            doShowCommentaireWindow();
        }
        else if(event.getButton().equals(btnValiderCommentaire))
        {
            doCommentaire();
        }
    }

    @Override
    public void onCommit(CommitEvent event)
    {
        doSauvegarder(event.getTrajetMidi());
    }
    
    
    private void doSauvegarder(TrajetMidiFormBean bean)
    {
        TrajetService serviceTrajet = ApplicationContext.getInstance(TrajetService.class);
        
        Lieu lieuArrivee = bean.getLieu();
        if(lieuArrivee == null)
        {
            lieuArrivee = new Lieu();
            lieuArrivee.setNom(bean.getLieuNom());
            lieuArrivee.setAdresse(bean.getLieuAdresse() != null ? bean.getLieuAdresse() : "");
        }
        
        Integer idTrajet = ((RootUI)getUI()).getCurrentTrajetMidiId();
        Trajet trajet;
        
        if(idTrajet == null) {
            // Ajout
            trajet = new Trajet();
            trajet.setCreatedBy(currentUtilisateur);
            trajet.setJour(new Date());
            trajet.setLieuDepart(currentUtilisateur.getEntreprise());
        } else {
            // Modification
            trajet = serviceTrajet.getById(idTrajet);
        }
        
        trajet.setLieuArrivee(lieuArrivee);
        
        try
        {
            trajet.setHeureDepart(new Time(dfTime.parse(bean.getHeureDepart()).getTime()));
            if(bean.getHeureRetour() != null) {
                trajet.setHeureRetour(new Time(dfTime.parse(bean.getHeureRetour()).getTime()));
            } else {
                trajet.setHeureRetour(null);
            }
            
        } catch(ParseException ex) {
            NotificationUtil.showExceptionNotification(ex);
        }
        
        trajet.setInformations(bean.getInformations());
        
        
        if(idTrajet == null) {
            trajet = serviceTrajet.addTrajet(trajet);
        } else {
            trajet = serviceTrajet.updateTrajet(trajet);
        }
        
        doAfterSauvegarder(trajet);
    }
    
    private void doShowInscriptionWindow()
    {
        if(winInscription == null)
        {
            tfNbPlaces = new TextField("Nb. de places que je propose");
            tfNbPlaces.setWidth(100, Unit.PERCENTAGE);

            btnValiderInscription = new Button("Valider");
            btnValiderInscription.addClickListener(this);

            VerticalLayout layout = new VerticalLayout();
            layout.setSpacing(true);
            layout.setMargin(true);
            layout.addComponent(tfNbPlaces);
            layout.addComponent(btnValiderInscription);
            layout.setComponentAlignment(btnValiderInscription, Alignment.BOTTOM_RIGHT);

            winInscription = new Window(btnInscription.getCaption(), layout);
            winInscription.setModal(true);
        }
        
        tfNbPlaces.setValue("0");
        
        getUI().addWindow(winInscription);
    }
    
    private void doInscription()
    {
        Trajet trajet = null;
                
        try
        {
            Integer nbPlaces = Integer.parseInt(tfNbPlaces.getValue());
     
            TrajetService serviceTrajet = ApplicationContext.getInstance(TrajetService.class);
            Integer idTrajet = ((RootUI)getUI()).getCurrentTrajetMidiId();
            trajet = serviceTrajet.getById(idTrajet);
            
            TrajetUtilisateur trajetUtilisateur = null;
            
            List<TrajetUtilisateur> lstTrajetUtilisateur = trajet.getInteresses();
            if(lstTrajetUtilisateur != null)
            {
                for(TrajetUtilisateur tu : lstTrajetUtilisateur)
                {
                    if(tu.getUtilisateur().getId().intValue() == currentUtilisateur.getId().intValue()) {
                        trajetUtilisateur = tu;
                        break;
                    }
                }
            }
            else
            {
                trajet.setInteresses(new ArrayList<TrajetUtilisateur>());
            }
            
            String sujetMail;
            
            if(trajetUtilisateur == null)
            {
                TrajetUnitisateurId trajetUtilisateurId = new TrajetUnitisateurId();
                trajetUtilisateurId.setFkTrajet(idTrajet);
                trajetUtilisateurId.setFkUtilisateur(currentUtilisateur.getId());

                trajetUtilisateur = new TrajetUtilisateur();
                trajetUtilisateur.setId(trajetUtilisateurId);
                trajetUtilisateur.setTrajet(trajet);
                trajetUtilisateur.setUtilisateur(currentUtilisateur);
                trajetUtilisateur.setNbPlaces(nbPlaces);
                
                trajet.getInteresses().add(trajetUtilisateur);
                
                sujetMail = "Nouvel inscrit sur le trajet ";
            }
            else
            {
                trajetUtilisateur.setNbPlaces(nbPlaces);
                
                sujetMail = "Modification d'inscription sur le trajet ";
            }
            
            serviceTrajet.updateTrajet(trajet);
            
            // Envoi d'un mail à tous les interesses
            MailService serviceMail = ApplicationContext.getInstance(MailService.class);
            
            List<String> destinataires = new ArrayList<String>();
            int nbPlacesTrajet = 0;
            for(TrajetUtilisateur tu : trajet.getInteresses())
            {
                destinataires.add(tu.getUtilisateur().getEmail());
                nbPlacesTrajet += tu.getNbPlaces() != null ? tu.getNbPlaces().intValue() : 0;
            }
            
            StringBuilder sujet = new StringBuilder();
            sujet.append(sujetMail);
            sujet.append(trajet.getLieuArrivee().getNom());
            
            StringBuilder message = new StringBuilder();
            message.append("<html><body>");
            message.append(sujetMail)
                   .append(trajet.getLieuArrivee().getNom())
                   .append(" :<br><br>");
            message.append("&nbsp;- Nom : ")
                   .append(currentUtilisateur.getNom())
                   .append("<br>");
            message.append("&nbsp;- Nb. de places proposées : ")
                   .append(nbPlaces)
                   .append("<br><br>");
            message.append("Rappel du trajet :<br><br>");
            message.append("&nbsp;- Lieu : ")
                   .append(trajet.getLieuArrivee().getNom())
                   .append("<br>");
            message.append("&nbsp;- Adresse : ")
                   .append(trajet.getLieuArrivee().getAdresse())
                   .append("<br>");
            message.append("&nbsp;- Horaires : ")
                   .append(" départ à ")
                   .append(dfTime.format(trajet.getHeureDepart()));
            if(trajet.getHeureRetour() != null)
            {
                message.append("retour vers  ")
                   .append(dfTime.format(trajet.getHeureRetour()));
            }
            message.append("<br>");
            message.append("&nbsp;- Nb. d'inscrits : ")
                   .append(trajet.getInteresses().size())
                   .append("<br>");
            message.append("&nbsp;- Nb. de places proposées : ")
                   .append(nbPlacesTrajet)
                   .append("<br><br><br>");
            message.append("Bon ecovoiturage !");
            message.append("</body></html>");
            
            serviceMail.sendMail(destinataires, sujet.toString(), message.toString());
            
            
            winInscription.close();
            refreshInteresses(trajet);
            
        } catch(NumberFormatException ex) {
            NotificationUtil.showWarningNotification("Format de nombre incorrect");
        } catch(MailException ex) {
            NotificationUtil.showWarningNotification("Inscription/modification réussie, mais le mail n'a pas été envoyé");
            winInscription.close();
            refreshInteresses(trajet);
        }
    }
    
    private void doDeinscription()
    {
        TrajetService serviceTrajet = ApplicationContext.getInstance(TrajetService.class);
        Integer idTrajet = ((RootUI)getUI()).getCurrentTrajetMidiId();
        Trajet trajet = serviceTrajet.getById(idTrajet);
        
        if(trajet.getInteresses() != null)
        {
            Iterator<TrajetUtilisateur> iterator = trajet.getInteresses().iterator();
            TrajetUtilisateur trjutil;
            while(iterator.hasNext())
            {
                trjutil = iterator.next();
                
                if(trjutil.getUtilisateur().getId().intValue() == currentUtilisateur.getId().intValue()) {
                    iterator.remove();
                    break;
                }
            }
            
            serviceTrajet.updateTrajet(trajet);
            
            try
            {
                // Envoi d'un mail à tous les interesses
                MailService serviceMail = ApplicationContext.getInstance(MailService.class);

                String sujetMail = currentUtilisateur.getNom()+" se désincrit du trajet ";

                List<String> destinataires = new ArrayList<String>();
                destinataires.add(currentUtilisateur.getEmail());
                int nbPlacesTrajet = 0;
                for(TrajetUtilisateur tu : trajet.getInteresses())
                {
                    destinataires.add(tu.getUtilisateur().getEmail());
                    nbPlacesTrajet += tu.getNbPlaces() != null ? tu.getNbPlaces().intValue() : 0;
                }

                StringBuilder sujet = new StringBuilder();
                sujet.append(sujetMail);
                sujet.append(trajet.getLieuArrivee().getNom());

                StringBuilder message = new StringBuilder();
                message.append("<html><body>");
                message.append(sujetMail)
                       .append(trajet.getLieuArrivee().getNom())
                       .append(".<br><br>");
                message.append("Rappel du trajet :<br><br>");
                message.append("&nbsp;- Lieu : ")
                       .append(trajet.getLieuArrivee().getNom())
                       .append("<br>");
                message.append("&nbsp;- Adresse : ")
                       .append(trajet.getLieuArrivee().getAdresse())
                       .append("<br>");
                message.append("&nbsp;- Horaires : ")
                       .append(" départ à ")
                       .append(dfTime.format(trajet.getHeureDepart()));
                if(trajet.getHeureRetour() != null)
                {
                    message.append("retour vers  ")
                       .append(dfTime.format(trajet.getHeureRetour()));
                }
                message.append("<br>");
                message.append("&nbsp;- Nb. d'inscrits : ")
                       .append(trajet.getInteresses().size())
                       .append("<br>");
                message.append("&nbsp;- Nb. de places proposées : ")
                       .append(nbPlacesTrajet)
                       .append("<br><br><br>");
                message.append("Bon ecovoiturage !");
                message.append("</body></html>");

                serviceMail.sendMail(destinataires, sujet.toString(), message.toString());
                
            } catch(MailException ex) {
                NotificationUtil.showWarningNotification("Désincription réussie, mais le mail n'a pas été envoyé");
            }
            
            refreshInteresses(trajet);
        }
    }
    
    private void doShowCommentaireWindow()
    {
        if(winCommentaire == null)
        {
            taCommentaire = new TextArea();
            taCommentaire.setWidth(100, Unit.PERCENTAGE);

            btnValiderCommentaire = new Button("Valider");
            btnValiderCommentaire.addClickListener(this);

            VerticalLayout layout = new VerticalLayout();
            layout.setSpacing(true);
            layout.setMargin(true);
            layout.addComponent(taCommentaire);
            layout.addComponent(btnValiderCommentaire);
            layout.setComponentAlignment(btnValiderCommentaire, Alignment.BOTTOM_RIGHT);

            winCommentaire = new Window(btnCommentaire.getCaption(), layout);
            winCommentaire.setWidth(500, Unit.PIXELS);
            winCommentaire.setModal(true);
        }
        
        taCommentaire.setValue("");
        
        getUI().addWindow(winCommentaire);
    }
    
    private void doCommentaire()
    {
        if(taCommentaire.getValue() == null || taCommentaire.getValue().isEmpty())
        {
            NotificationUtil.showWarningNotification("Il manque le commentaire...");
        }
        else
        {
            TrajetService serviceTrajet = ApplicationContext.getInstance(TrajetService.class);
            Integer idTrajet = ((RootUI)getUI()).getCurrentTrajetMidiId();
            Trajet trajet = serviceTrajet.getById(idTrajet);

            TrajetCommentaire trajetCommentaire = new TrajetCommentaire();
            trajetCommentaire.setTrajet(trajet);
            trajetCommentaire.setUtilisateur(currentUtilisateur);
            trajetCommentaire.setDate(Calendar.getInstance());
            trajetCommentaire.setCommentaire(taCommentaire.getValue());
            
            if(trajet.getCommentaires() == null) {
                trajet.setCommentaires(new ArrayList<TrajetCommentaire>());
            }
            
            trajet.getCommentaires().add(trajetCommentaire);
            
            serviceTrajet.updateTrajet(trajet);
            
            try
            {
                // Envoi d'un mail à tous les interesses
                MailService serviceMail = ApplicationContext.getInstance(MailService.class);

                String sujetMail = "Un nouveau commentaire de "+currentUtilisateur.getNom()+" pour le trajet ";

                List<String> destinataires = new ArrayList<String>();
                for(TrajetUtilisateur tu : trajet.getInteresses()) {
                    destinataires.add(tu.getUtilisateur().getEmail());
                }

                StringBuilder sujet = new StringBuilder();
                sujet.append(sujetMail);
                sujet.append(trajet.getLieuArrivee().getNom());

                StringBuilder message = new StringBuilder();
                message.append("<html><body>");
                message.append(sujetMail)
                       .append(trajet.getLieuArrivee().getNom())
                       .append(" :<br><br>");
                message.append(taCommentaire.getValue())
                       .append("<br><br><br>");
                message.append("Bon ecovoiturage !");
                message.append("</body></html>");

                serviceMail.sendSeparateMail(destinataires, sujet.toString(), message.toString());
                
            } catch(MailException ex) {
                NotificationUtil.showWarningNotification("Commentaire ajouté, mais le mail n'a pas été envoyé");
            }
            
            winCommentaire.close();
            lstCommentaires.setCommentaires(trajet.getCommentaires());
        }
    }
    
    
    private void refreshInteresses(Trajet trajet)
    {
        List<TrajetMidiInteresseItem> interesses = new ArrayList<TrajetMidiInteresseItem>();
        if(trajet.getInteresses() != null)
        {
            TrajetMidiInteresseItem item;
            for(TrajetUtilisateur tu : trajet.getInteresses())
            {
                item = new TrajetMidiInteresseItem();
                item.setNomInteresse(tu.getUtilisateur().getNom());
                item.setNbPlaces(tu.getNbPlaces() != null ? tu.getNbPlaces() : 0);

                interesses.add(item);
            }

            tblInteresses.setInteresses(interesses);
        }
    }
}
